% !TeX program = xelatex 
\documentclass[xcolor=svgnames,10pt,UTF8]{ctexbeamer}
%\documentclass[aspectratio=169,xcolor=svgnames,10pt]{beamer}

\RequirePackage{slide}

\logo{\includegraphics[scale=0.02]{../figure/logo.jpg}}
\title{SystemVerilog芯片验证}
\subtitle{第2章~测试平台和数据类型}
%\author{王旭}
%\institute{深圳信息职业技术学院~微电子学院}
%\date{\today}

\begin{document}

\frame{\titlepage}
\LogoOn
\LogoOff

\section{测试平台} \label{sec Testbench and DUT}

\begin{frame}[t,fragile]{测试平台：生成激励，捕获响应，判别对错和测量进度}

\begin{figure}[!htb]
	\centering%\captionsetup{font={small}} %small or scriptsize
	%\tikzstyle{every node}=[font=\normalsize]
	\scalebox{1.0}{
		\begin{tikzpicture}
			% \draw[step=1,color=gray!40] (0,0) grid (8,4);
			\begin{pgfonlayer}{background}
				\node[thick,draw,fill=gray!10,rectangle,minimum height=4.5cm,minimum width=7cm] (Top) at (3,1.1) {};
				\node[thick,fill=gray!10,align=center] at (3,-0.5) {顶层模块top\_tb};
			\end{pgfonlayer}
			\begin{pgfonlayer}{foreground}
				\node[thick,color=blue,draw,fill=red!20,align=center,rectangle,minimum height=3cm,minimum width=2cm] (test) at (1,1.5) {测试模块\\test};
				\node[thick,color=red,draw,fill=orange!20,rectangle,minimum height=3cm,minimum width=2cm] (RAM) at (5,1.5) {DUT};
				%\node[thick] (CLK) at (3,-0.5) {Clock};
				\draw [thick,Latex-Latex] (2,2.5) to node [above] {clk} (4,2.5);
				\draw [thick,Latex-Latex] (2,2.0) to node [above] {rst\_n} (4,2.0);
				\draw [thick,-Latex] (2,1.5) to node [above] {a} (4,1.5);
				\draw [thick,-Latex] (2,1.0) to node [above] {b} (4,1.0);
				\draw [thick,-Latex] (4,0.5) to node [above] {sum} (2,0.5);
				%\draw [thick,] (3,0.5) node [circle,draw,fill=black,scale=0.4] {} -- (CLK);
			\end{pgfonlayer}
		\end{tikzpicture}
	}
	%\caption{测试平台的基本结构} \label{verilog testbench struture}
\end{figure}

\end{frame}

\subsection{被测设计} \label{subsec DUT module}

\begin{frame}[t,fragile]{加法器模块}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-15},consecutivenumbers=false]%,caption=加法器模块\\\lstname,label=adder model using ports]
{src/ch2/sec1/1/dut.sv}

参数化类型也被称为泛型，其本质是将操作的数据类型定义成类型参数（type parameter），在模块、类、接口和函数的定义中都可以使用参数化类型。

\end{frame}

\begin{frame}[t,fragile]{加法器模块端口描述}

\begin{table}[!htb]
	\centering\captionsetup{font={footnotesize}}\footnotesize %small or scriptsize
	%\caption{加法器模块的端口描述} \label{adder port description}
	\begin{tabular}{llll}
		\hline
		\rowcolor{black!10}信号名 & 方向     & 位宽      & 描述      \\\hline
		clk                    & input  & 1       & 时钟      \\\hline
		rst\_n                 & input  & 1       & 异步低电平复位 \\\hline
		a                      & input  & WIDTH-1 & 加数      \\\hline
		b                      & input  & WIDTH-1 & 被加数     \\\hline
		sum                    & output & WIDTH   & 求和结果    \\\hline
	\end{tabular}
\end{table}

\end{frame}

\subsection{测试模块} \label{subsec test module}

\begin{frame}[t,fragile]{测试模块}
	
测试模块被定义为自动（automatic）类型。

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-4,11-28},consecutivenumbers=false]%,caption=测试模块\\\lstname,label=test module using ports]
{src/ch2/sec1/1/test.sv}

\end{frame}

\begin{frame}[t,fragile]{避免使用程序块}

在测试平台中避免使用程序块。

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-4,28-28},consecutivenumbers=false]%,caption=测试程序块\\\lstname,label=test program using ports]
{src/ch2/sec1/2/test.sv}

\end{frame}

\subsection{测试平台顶层模块} \label{subsec top module}

\begin{frame}[t,fragile]{波形生成}

\begin{enumerate}
	\item \$fsdbDumpfile：指定转存的文件名为“wave.fsdb”。
	\item \$fsdbDumpvars：转存top\_tb模块下所有层级的信号和变量，包括结构类型变量。
	\item \$fsdbDumpMDA：参数0表示转存top\_tb模块下所有层级中的多维数组。
	\item \$fsdbDumpSVA：转存断言（assertion）。
\end{enumerate}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={22-27},consecutivenumbers=false]%,caption=顶层模块\\\lstname,label=top_tb module with ports]
{src/ch2/sec1/1/top_tb.sv}

\end{frame}

\begin{frame}[t,fragile]{时钟和异步复位生成}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={11-20},consecutivenumbers=false]%,caption=顶层模块\\\lstname,label=top_tb module with ports]
{src/ch2/sec1/1/top_tb.sv}

\end{frame}

\begin{frame}[t,fragile]{连接测试模块和DUT}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={29-41},consecutivenumbers=false]%,caption=顶层模块\\\lstname,label=top_tb module with ports]
{src/ch2/sec1/1/top_tb.sv}

\end{frame}

\section{基本数据类型} \label{Basic Data Types}

\subsection{reg和wire类型} \label{subsec reg and wire type}

\begin{frame}[t,fragile]{reg和wire类型}

	\begin{enumerate}
		\item 变量和连线数据类型用来描述不同的硬件结构。
		\item reg属于变量数据类型，用于过程赋值（procedural assignment），默认初始值是不定值。
		\item wire属于连线数据类型，用于连续赋值（continuous assignment），还可以用来连接代码中的门级原语和模块实例。
	\end{enumerate}
\end{frame}

\subsubsection{描述组合电路} \label{subsubsec description comb logic}

\begin{frame}[t,fragile]{描述组合电路}

reg和wire类型都可以用来描述组合电路。

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-13},consecutivenumbers=false]%,caption=使用reg类型描述组合电路\\\lstname,label=reg and wire to build comb]
{src/ch2/sec2/1/dut.sv}

\begin{lstlisting}
@0, a=x, b=x, c=x, d=x, e=x, f=x
@10000, a=0, b=0, c=0, d=0, e=0, f=0
@20000, a=1, b=1, c=2, d=2, e=0, f=2
@30000, a=2, b=1, c=3, d=3, e=0, f=2
\end{lstlisting}

\end{frame}

\subsubsection{描述时序电路} \label{subsubsec description sequential}

\begin{frame}[t,fragile]{描述时序电路}

reg类型可以用来描述时序电路。

\begin{lstlisting}[language=SystemVerilog,numbers=left,consecutivenumbers=false]%,caption=使用reg类型描述D触发器\\\lstname,label=description d trigger using reg type]
reg q;
always @(posedge clk)
	q <= d; // 非阻塞赋值
\end{lstlisting}

\begin{figure}[!htb]
	\centering
	\tikzstyle{every node}=[font=\normalsize, scale=1.0]
	\begin{circuitikz}[american]
		\ctikzset{logic ports=ieee}
		\draw (0,0) node[latch, anchor=pin 1](ff1) {}
		(ff1.pin 1) to[short] ++(0,0) node[left] {d}
		(ff1.pin 6) to[short] ++(0,0) node[right] {q}
		(ff1.pin 3) to[short] ++(0,0) node[left]{clk}
		;
	\end{circuitikz}
	%\caption{D触发器} \label{fig d trigger}
\end{figure}

输入端d的值需要在时钟上升沿前后保持足够长的稳定时间，d的值才能在时钟上升沿到来时正确传递到输出端q。

\begin{figure}[!htb]
	\centering
	\tikzstyle{every node}=[font=\normalsize, scale=1.0]
	\begin{tikztimingtable}
		\textrm{clk} & L 6{4C} 3C\\
		\textrm{d} & 1U 8D{1'b1} 8D{1'b0} 11D{1'b1} \\
		\textrm{q} & 9U 8D{1'b1} 8D{1'b0} 3D{1'b1} \\
		\extracode
		%\tablerules
		\begin{pgfonlayer}{background}
			%\foreach \n in {1,...,8}
			%\draw [help lines] (A\n) -- (B\n);
			\vertlines[help lines]{1,9,17,25}
		\end{pgfonlayer}
	\end{tikztimingtable}
	%\caption{D触发器的时序} \label{fig timing d trigger}
\end{figure}

\end{frame}

\subsubsection{阻塞赋值与非阻塞赋值} \label{subsubsec blocking and noblocking assignment}

\begin{frame}[t,fragile]{阻塞赋值与非阻塞赋值}

在always过程中使用阻塞赋值描述组合电路，使用非阻塞赋值描述时序电路。

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-13},consecutivenumbers=false]%,caption=使用非阻塞赋值描述时序电路\\\lstname,label=nonblocking assignment to build seq]
{src/ch2/sec2/2/dut.sv}

\begin{figure}[!htb]
	\centering
	\tikzstyle{every node}=[font=\normalsize, scale=0.9]
	\begin{circuitikz}[american]
		\ctikzset{logic ports=ieee}
		\draw (0,0) node[latch, anchor=pin 1](ff1) {}
		(ff1.pin 1) to[short] ++(0,0) node[left] {a}
		(ff1.pin 6) node[above] {b}
		(ff1.pin 6) to[short] ++(0.5,0) node[twoportshape, anchor=left, t={+1}](add1) {}
		(add1.right) to[short] ++(0.5,0) node[latch, anchor=pin 1](ff2) {}
		(ff2.pin 6) to[short] ++(0,0) node[right]{c}
		(ff1.pin 3) to[short] ++(0,-0.8) node[] (p) {} to[short] ++(-0.5,0) node[left] {clk}
		(p.center) to[short,*-] ++(0,0) -| (ff2.pin 3)
		;
	\end{circuitikz}
	%\caption{always过程中非阻塞赋值对应的电路结构} \label{fig nonblocking assignment}
\end{figure}

\end{frame}

\begin{frame}[t,fragile]{阻塞赋值在描述时序电路时存在很严重的缺陷}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={9-15},consecutivenumbers=false]%,caption=使用阻塞赋值描述时序电路\\\lstname,label=blocking assignment to build seq]
{src/ch2/sec2/3/dut.sv}

\begin{figure}[htbp]
	\centering
	\tikzstyle{every node}=[font=\normalsize, scale=0.9]
	\begin{circuitikz}[american]
		\ctikzset{logic ports=ieee}
		\draw (0,0) node[latch, anchor=pin 1](ff1) {}
		(ff1.pin 1) to[short] ++(-0.5,0) node[left] {a}
		(ff1.pin 6) ++(1.0,0) node[latch, anchor=pin 1](ff2) {}
		(ff1.pin 6) to[short] ++(0,0) node[right] {b}
		(ff1.pin 1) to[short,*-] ++(0,0) |- ++(0.3,1.2) node[twoportshape, anchor=left, t={+1}](add1) {}
		(add1.right) -|(ff2.pin 1)
		(ff2.pin 6) to[short] ++(0.5,0) node[right]{c}
		(ff2.pin 6) to[short,*-] ++(0,-0.5) to[short] ++(0.5,0.0) node[right]{d}
		(ff1.pin 3) to[short] ++(0,-0.8) node[] (p) {} to[short] ++(-0.5,0) node[left] {clk}
		(p.center) to[short,*-] ++(0,0) -| (ff2.pin 3)
		;
	\end{circuitikz}
	%\caption{always过程中阻塞赋值对应的电路结构} \label{fig blocking assignment}
\end{figure}

\end{frame}

\subsection{四值logic类型} \label{The Logic Type}

\begin{frame}[t,fragile]{四值logic类型}

\begin{enumerate}
	\item logic类型可以用于所有reg和wire的使用场景。
	\item logic类型不能像wire类型那样支持多驱动。
	\item logic变量有4种可能取值，分别是0、1、z或x，默认值是x。
\end{enumerate}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-9},consecutivenumbers=false]%,caption=使用logic替换测试模块中的reg和wire\\\lstname,label=test module add logic]
{src/ch2/sec2/4/test.sv}

\end{frame}

\subsection{二态数据类型} \label{2-State Data Types}

\begin{frame}[t,fragile]{二态数据类型}

将硬件设计与软件测试分离开。软件测试（验证环境）中应该尽量使用二态逻辑，二态逻辑的默认值是0。

\begin{table}[!htb]
	\centering\captionsetup{font={footnotesize}}\footnotesize %small or scriptsize
	%\caption{常见的二态数据类型} \label{Some two state data types}
	\begin{tabular}{lll}
		\hline
		\rowcolor{black!10}类型                         & 描述            & 例子                                               \\\hline
		\lstinline[language=SystemVerilog]|bit|       & 二态无符号整数       & \lstinline[language=SystemVerilog]|bit [3:0] a;| \\\hline
		\lstinline[language=SystemVerilog]|byte|      & 二态8位有符号整数     & \lstinline[language=SystemVerilog]|byte a;|      \\\hline
		%\lstinline[language=SystemVerilog]|byte unsigned| & 二态8位无符号整数 & \lstinline[language=SystemVerilog]|byte unsigned a;| \\\hline
		\lstinline[language=SystemVerilog]|shortint|  & 二态16位有符号整数    & \lstinline[language=SystemVerilog]|shortint a;|  \\\hline
		\lstinline[language=SystemVerilog]|int|       & 二态32位有符号整数    & \lstinline[language=SystemVerilog]|int a;|       \\\hline
		\lstinline[language=SystemVerilog]|longint|   & 二态64位有符号      & \lstinline[language=SystemVerilog]|longint a;|   \\\hline
		\lstinline[language=SystemVerilog]|shortreal| & 二态32位有符号浮点数   & \lstinline[language=SystemVerilog]|shortreal a;| \\\hline
		\lstinline[language=SystemVerilog]|real|      & 二态64位有符号浮点数   & \lstinline[language=SystemVerilog]|real a;|      \\\hline
		\lstinline[language=SystemVerilog]|realtime|  & 二态64位有符号浮点数时间 & \lstinline[language=SystemVerilog]|realtime rt;| \\\hline
		\lstinline[language=SystemVerilog]|integer|   & 四值32位有符号整数    & \lstinline[language=SystemVerilog]|integer a;|   \\\hline
		\lstinline[language=SystemVerilog]|time|      & 四值64位无符号整数时间  & \lstinline[language=SystemVerilog]|time t;|      \\\hline
	\end{tabular}
\end{table}

\end{frame}

\begin{frame}[t,fragile]{二态数据类型使用}

	\begin{enumerate}
		\item 数据类型的符号和取值范围（sum溢出）。
		\item 四值到二态的数据类型转换时，数值z和x会被转换成二态数据类型的默认值0。
	\end{enumerate}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-15},consecutivenumbers=false]%,caption=二态数据类型的使用\\\lstname,label=A wrong adder]
{src/ch2/sec2/5/test.sv}

\begin{lstlisting}
a=127, b=1, sum=-128
c=x, b=0
\end{lstlisting}

\end{frame}

\subsection{向量的位选与块选} \label{subsec vector bit-select and part-select}

\begin{frame}[t,fragile]{向量的位选与块选}

\begin{enumerate}
	\item 非索引块选（non-indexed part-select）：即\texttt{[msb\_expr:lsb\_expr]}。其中\texttt{msb\_expr}和\texttt{lsb\_expr}都是常量整数表达式。
	\item 索引块选（indexed part-select）：即\texttt{[base\_expr+:width\_expr]}和\texttt{[base\_expr-:width\_expr]}，其中\texttt{base\_expr}可以是变量表达式，但\texttt{width\_expr}只能是正的常数表达式。\texttt{a[x+:c]}表示从变量\texttt{a}的第\texttt{x}位开始向索引变大的方向连续提取\texttt{c}位。\texttt{a[x-:c]}表示从变量\texttt{a}的第\texttt{x}位开始向索引变小的方向连续提取\texttt{c}位。
\end{enumerate}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-13},consecutivenumbers=false]
%,caption=向量的位选与块选\\\lstname,label=vector part select]
{src/ch2/sec2/6/test.sv}

\end{frame}

\subsection{常量和字符串} \label{Constants and Strings}

\begin{frame}[t,fragile]{常量}

\begin{enumerate}
	\item 宏定义（\verb|`|define）通常用于定义全局常量。
	\item 参数（parameter）通常用于定义局部常量。
	\item const类型变量在定义的同时进行初始化，它的内容无法更改。
\end{enumerate}

\begin{lstlisting}[language=SystemVerilog,numbers=left,consecutivenumbers=false]
initial const byte colon = ":";
\end{lstlisting}

\end{frame}

\begin{frame}[t,fragile]{字符串}

string类型变量用来保存长度可变的字符串，一个长度为n的字符串的元素序号为0到n-1。SystemVerilog的字符串的结尾不带“\textbackslash0”。

\begin{table}[!htb]
	\centering\captionsetup{font={footnotesize}}\footnotesize %small or scriptsize
	%\caption{常用的字符串方法} \label{some string methods}%
	\begin{tabular}{ll}
		\hline
		\rowcolor{black!10}方法                                                    & 说明                     \\\hline
		\lstinline[language=SystemVerilog]|function int len()|                   & 返回字符串的长度               \\\hline
		\lstinline[language=SystemVerilog]|function void putc(int i, byte c)|    & 将字符c写入字符串的位置i中         \\\hline
		\lstinline[language=SystemVerilog]|function byte getc(int i)|            & 提取位置i上的字符              \\\hline
		\lstinline[language=SystemVerilog]|function string toupper()|            & 返回所有字符大写的字符串           \\\hline
		\lstinline[language=SystemVerilog]|function string tolower()|            & 返回字符小写的字符串             \\\hline
		\lstinline[language=SystemVerilog]|function int compare(string s)|       & 区分字母大小写比较              \\
		例如\lstinline[language=SystemVerilog]|str.compare(s)|                     & str大于s返回1，等于返回0，小于返回-1 \\\hline
		\lstinline[language=SystemVerilog]|function int icompare(string s)|      & 不区分字母大小写比较             \\
		例如\lstinline[language=SystemVerilog]|str.icompare(s)|                    & str大于s返回1，等于返回0，小于返回-1 \\\hline
		\lstinline[language=SystemVerilog]|function string substr(int i, int j)| & 提取出位置i到j之间的字符串         \\\hline
		\lstinline[language=SystemVerilog]|str == s|                             & 区分字母大小写比较，等于返回1，否则返回0  \\\hline
		\lstinline[language=SystemVerilog]|{}|                                   & 拼接字符串                  \\\hline
	\end{tabular}%
\end{table}%

\end{frame}

\begin{frame}[t,fragile]{}

\$sformatf方法返回一个格式化的临时字符串。

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-16},consecutivenumbers=false]
{src/ch2/sec2/6/test.sv}

\begin{lstlisting}
65
abcd
ABCD
bc
Abc EF 0
\end{lstlisting}

\end{frame}

\section{时间值} \label{Time Values}

\begin{frame}[t,fragile]{`timescale设置全局的时间单位和时间精度}

\begin{minipage}{0.47\textwidth}
	\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-4},consecutivenumbers=false]
	{src/ch2/sec3/1/ns.sv}
\end{minipage}
\begin{minipage}{0.47\textwidth}
	\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-4},consecutivenumbers=false]
	{src/ch2/sec3/1/ps.sv}
\end{minipage}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-15},consecutivenumbers=false]
{src/ch2/sec3/1/test.sv}

\begin{minipage}{0.47\textwidth}
	\begin{lstlisting}
1.000ns
3.000ns
3.000ns
3.000ns
\end{lstlisting}
\end{minipage}
\begin{minipage}{0.47\textwidth}
	\begin{lstlisting}
1.000ns
3.000ns
3.100ns
3.141ns
\end{lstlisting}
\end{minipage}

\end{frame}

\subsection{时间常量} \label{Time Literals}

\begin{frame}[t,fragile]{timeunit和timeprecision}

指定局部可见的时间单位和精度。

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-14},consecutivenumbers=false]%,caption=在模块内设置时间单位和精度\\\lstname,label=time literals and timeformat]
{src/ch2/sec3/2/test.sv}

\begin{lstlisting}
1.000ns
3.000ns
3.100ns
3.141ns
\end{lstlisting}

\end{frame}

\begin{frame}[t,fragile]{系统任务\$timeformat}

系统任务\$timeformat用来设置打印时间的格式，它的四个参数分别表示时间的单位值、精度、后缀字符串以及最小显示宽度。系统任务\$time可根据当前所在模块的时间单位返回当前的整数时间（舍去时间的小数部分），而\$realtime则是返回一个完整的带小数部分的当前时间。

\begin{table}[!htb]
	\centering\captionsetup{font={footnotesize}}\footnotesize %small or scriptsize
	%\caption{系统任务\$timeformat的参数值说明} \label{timeformat units_number arguments}%
	\begin{tabular}{llll}
		\hline
		\rowcolor{black!10}参数值 & 时间单位  & 参数值 & 时间单位  \\\hline
		0                      & 1s    & -8  & 10ns  \\\hline
		-1                     & 100ms & -9  & 1ns   \\\hline
		-2                     & 10ms  & -10 & 100ps \\\hline
		-3                     & 1ms   & -11 & 10ps  \\\hline
		-4                     & 100us & -12 & 1ps   \\\hline
		-5                     & 10us  & -13 & 100fs \\\hline
		-6                     & 1us   & -14 & 10fs  \\\hline
		-7                     & 100ns & -15 & 1fs   \\\hline
	\end{tabular}%
\end{table}%

\end{frame}

\subsection{时间变量} \label{Time and Variables}

\begin{frame}[t,fragile]{时间变量}

64位无符号整数的time类型和64位有符号浮点数的realtime类型。time变量会根据当前的时间单位和时间精度对时间值进行四舍五入，它不能保存小数延迟。

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-14},consecutivenumbers=false]
{src/ch2/sec3/3/test.sv}

\begin{lstlisting}
800ps
1000ps
\end{lstlisting}

\end{frame}

\section{数组} \label{sec Packed and unpacked arrays}

\subsection{非压缩数组} \label{subsec unpacked array}

\begin{frame}[t,fragile]{定义非压缩数组时，数组的长度写在变量名后}

长度固定的非压缩数组被称为定长数组，长度不固定的非压缩数组被称为动态数组。

\begin{lstlisting}[language=SystemVerilog,numbers=left,consecutivenumbers=false]
byte a[2]; // 等价于byte a[0:1];
\end{lstlisting}

\begin{figure}[!htb]
	\centering%\captionsetup{font={small}}\small %small or scriptsize
	\scalebox{0.8}{
		\begin{tikzpicture}
			\tikzstyle{every node}=[font=\normalsize]
			% \draw[step=1,color=gray] (0,0) grid (28,6);
			\foreach \y\ytext in {0/a[1],0.7/a[0]}
			{
				\node[draw,rectangle,minimum height=0.7cm,minimum width=6.0cm] at (3,\y+0.35) {高24位未使用};
				\node[draw,fill={black!10},rectangle,minimum height=0.7cm,minimum width=2cm] at (7,\y+0.35) {\ytext};
			}
		\end{tikzpicture}
	}
	%\caption{数组a的存储方式} \label{Unpacked array storage}
\end{figure}

访问数组时下标超出地址边界，返回数组类型的默认值。使用系统函数\$clog2计算存储器的地址位宽。

\begin{lstlisting}[language=SystemVerilog,numbers=left,consecutivenumbers=false]
parameter int MEM_SIZE = 256;
parameter int ADDR_WIDTH = $clog2(MEM_SIZE); // $clog2(256) = 8
bit [15:0] mem[MEM_SIZE];
bit [ADDR_WIDTH-1:0] addr; // [7:0]
\end{lstlisting}

\end{frame}

\subsection{压缩数组} \label{Packed Arrays}

\begin{frame}[t,fragile]{压缩（packed）数组，灵活访问连续比特流数据}

\begin{enumerate}
	\item 压缩数组的维度写在数组名的前面。
	\item bit、reg或wire类型的矢量变量通常被称为一维压缩数组。	
	\item 两个维度不同但总长度相等的数组a和b可以进行整体的赋值和比较。
\end{enumerate}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-14},consecutivenumbers=false]%,caption=压缩数组的定义和使用\\\lstname,label=Packed array declaration and usage]
{src/ch2/sec4/1/test.sv}

\begin{figure}[!htb]
	\centering\captionsetup{font={footnotesize}}\footnotesize %small or scriptsize
	\scalebox{0.6}{
		\begin{tikzpicture}
			\tikzstyle{every node}=[font=\normalsize]
			% \draw[step=1,color=gray] (0,0) grid (28,6);
			\foreach \c in {0,4.8,9.6,14.4}
				{
					\foreach \x/\xtext in {0/7,0.6/6,1.2/5,1.8/4,2.4/3,3/2,3.6/1,4.2/0}
						{
							\node[draw,fill=black!10,rectangle,minimum height=0.6cm,minimum width=0.6cm] at (\x+\c+0.3,0.3) {\xtext};
						}
				}
			\draw[decorate,decoration={brace,amplitude=0.4cm}] (0,0.6) -- (9.6,0.6);
			\draw[decorate,decoration={brace,amplitude=0.4cm}] (4.8,0) -- (0,0);
			\draw[decorate,decoration={brace,amplitude=0.4cm}] (12,0.6) -- (14.4,0.6);
			\draw[-Latex] (16.5,0.6) -- (16.5,1);
			\node at (-0.3,0.3) {b};
			\node at (4.8,1.3) {b[3:2]};
			\node at (2.4,-0.8) {b[3]};
			\node at (13.2,1.3) {b[1][3:0]};
			\node at (16.5,1.3) {b[0][4]};
		\end{tikzpicture}
	}
	%\caption{压缩数组的存储方式} \label{Packed array layout}
\end{figure}

\end{frame}

\begin{frame}[t,fragile]{压缩数组和非压缩数组同时使用}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-16},consecutivenumbers=false]%,caption=压缩和非压缩数组的混用\\\lstname,label=using mixed array]
{src/ch2/sec4/2/test.sv}

\begin{lstlisting}
00000001111111101101101010111010 00000001 1 1011
\end{lstlisting}

\begin{figure}[!htb]
	\centering\captionsetup{font={footnotesize}}\footnotesize %small or scriptsize
	\scalebox{0.5}{
		\begin{tikzpicture}
			\tikzstyle{every node}=[font=\normalsize]
			% \draw[step=1,color=gray] (0,0) grid (28,6);
			\foreach \y\ytext in {0/a[1],0.6/a[0]}
			{

			\node at (-0.5,\y+0.3) {\ytext};
			\foreach \c in {0,4.8,9.6,14.4}
				{
					\foreach \x/\xtext in {0/7,0.6/6,1.2/5,1.8/4,2.4/3,3/2,3.6/1,4.2/0}
						{
							\node[draw,fill=black!10,rectangle,minimum height=0.6cm,minimum width=0.6cm] at (\x+\c+0.3,\y+0.3) {\xtext};
						}
				}
			}
			\draw[decorate,decoration={brace,amplitude=0.4cm}] (0,1.2) -- (4.8,1.2);
			\draw[-Latex] (9.9,1.2) -- (9.9,1.6);
			\draw[decorate,decoration={brace,amplitude=0.4cm}] (14.4,1.2) -- (16.8,1.2);
			\node at (2.4,1.9) {a[0][3]};
			\node at (9.9,1.9) {a[0][1][7]};
			\node at (15.6,1.9) {a[0][0][7:4]};
		\end{tikzpicture}
	}
	%\caption{非压缩和压缩数组的混用} \label{layout for a mixed array}
\end{figure}

\end{frame}

\subsection{数组直接量} \label{The Array Literal}

\begin{frame}[t,fragile]{数组直接量（array literal）带有单引号“'”}

\begin{enumerate}
	\item 而数组直接量可以描述多维数组，拼接运算符只能描述一维数组。
	\item 数组直接量可以内嵌拼接运算符。
\end{enumerate}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-17},consecutivenumbers=false]%,caption=使用数组直接量初始化数组\\\lstname,label=Initializing an array]
{src/ch2/sec4/3/test.sv}

\begin{lstlisting}[language=SystemVerilog,numbers=left,consecutivenumbers=false]
int a[2][3] = {'{0,1,2},'{3{4}}}; // 编译错误
\end{lstlisting}

\end{frame}

\subsection{数组遍历和foreach语句} \label{Basic Array Operations for and Foreach}

\begin{frame}[t,fragile]{一维数组的遍历}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-13},consecutivenumbers=false]%,caption=使用for和foreach遍历数组\\\lstname,label=using arrays with for and foreach loops]
{src/ch2/sec4/4/test.sv}

\begin{lstlisting}
0
1
2
3
0000 0 00
\end{lstlisting}

\end{frame}

\begin{frame}[t,fragile]{多维数组的遍历}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-16},consecutivenumbers=false]%,caption=遍历多维数组\\\lstname,label=step through a multi dimensional array]
{src/ch2/sec4/5/test.sv}

\begin{lstlisting}
a[0][0]=0
a[0][1]=1
a[1][0]=2
a[1][1]=2
0: 0 1
1: 2 2
\end{lstlisting}

\end{frame}

\begin{frame}[t,fragile]{变量的位遍历}

	\begin{enumerate}
		\item for语句从最低位开始遍历
		\item foreach语句最高位开始遍历
	\end{enumerate}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-14},consecutivenumbers=false]%,caption=使用foreach语句进行变量的位遍历\\\lstname,label=step through a variable]
{src/ch2/sec4/6/test.sv}

\begin{lstlisting}
00001111
11110000
\end{lstlisting}

\end{frame}

\subsection{数组的赋值和比较} \label{Basic Array Operations Copy and Compare}

\begin{frame}[t,fragile]{数组的整体赋值和比较（等于或不等于）}

不同长度的定长数组间的赋值会引起编译错误。

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-14},consecutivenumbers=false]%,caption=数组的赋值和比较操作\\\lstname,label=Array copy and compare operations]
{src/ch2/sec4/7/test.sv}

\begin{lstlisting}
a is not equal to b
a[1:4]==b[1:4]
\end{lstlisting}

\end{frame}

\section{动态数组} \label{sec Dynamic Arrays}

\begin{frame}[t,fragile]{动态数组运行时可以调整长度}

\begin{enumerate}
	\item 使用等号将一个数据类型相同的数组整体赋值给动态数组。
	\item 使用new操作符，方括号中指定数组长度，小括号中可选数组参数用于数组初始化。
\end{enumerate}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-18},consecutivenumbers=false]%,caption=使用动态数组\\\lstname,label=using dyuamic arrays]
{src/ch2/sec5/1/test.sv}

\begin{lstlisting}
'{0, 1, 2, 3, 4, 0, 0, 0, 0, 0}
\end{lstlisting}

\end{frame}

\begin{frame}[t,fragile]{多维动态数组}

动态数组带有常用内置方法，方法size用于计算动态数组的长度，方法delete用于释放动态数组的存储空间。定长数组没有内置的size方法，只能使用系统函数\$size计算数组长度。

多维动态数组中每个子数组的长度可以不相等。

\begin{lstlisting}[language=SystemVerilog,numbers=left,consecutivenumbers=false]
int d[][];
d = new[4]; // 创建第一维度
foreach(d[i]) d[i] = new[i+1]; // 创建第二维度
\end{lstlisting}

\end{frame}

\section{关联数组} \label{Associative Arrays}

\begin{frame}[t,fragile]{关联数组只为实际写入的数据分配存储空间}

\begin{figure}[!htb]
	\centering\captionsetup{font={footnotesize}}\footnotesize %small or scriptsize
	\scalebox{1.0}{
		\begin{tikzpicture}
			\tikzstyle{every node}=[font=\normalsize]
			%\draw[step=1,color=gray] (0,0) grid (10,2);
			\draw (0,0.5) rectangle (8.5,1);
			\foreach \x/\xtext in {0/0,1/10,2.5/100,4.5/1000,7.5/10000}
				{
					\filldraw[fill={black!10}] (\x,0.5) rectangle (\x+0.5,1);
					\node at (\x+0.25,0.25) {\xtext};
				}
			\node at (-1.0,0.75) {数据};
			\node at (-1.0,0.25) {地址};
		\end{tikzpicture}
	}
	%\caption{关联数组} \label{Associative array}
\end{figure}

\begin{enumerate}
	\item 定义关联数组时需要在数组名后的方括号中指定索引的数据类型。
	\item 注意如果关联数组的索引数据类型为通配符“*”，则表示它可以被任意位宽的整数表达式索引。
\end{enumerate}

\begin{lstlisting}[language=SystemVerilog,numbers=left,consecutivenumbers=false]
int a [byte unsigned]; // 索引数据类型为byte unsigned
bit [7:0] b [string]; // 索引数据类型为string
int c [*]; // 索引数据类型为通配符“*”
\end{lstlisting}

\end{frame}

\begin{frame}[t,fragile]{关联数组的常用内置查询方法}

first方法将关联数组的首个元素的索引值保存到参数index中，如果关联数组内容为空，则first方法的返回值为0，否则返回值为1。另外可以使用num或size方法查询关联数组的元素个数。

\begin{table}[!htb]
	\centering\captionsetup{font={footnotesize}}\footnotesize %small or scriptsize
	%\caption{关联数组的常用查询方法} \label{associative Arrays methods declaration}%
	\begin{tabular}{ll}
		\hline
		\rowcolor{black!10}方法名                                             & 说明                     \\\hline
		\lstinline[language=SystemVerilog]|function int first(ref index)|  & 返回关联数组第一个元素的索引值        \\\hline
		\lstinline[language=SystemVerilog]|function int last(ref index)|   & 返回关联数组最后一个元素的索引值       \\\hline
		\lstinline[language=SystemVerilog]|function int next(ref index)|   & 返回关联数组当前位置的下一个元素的索引值   \\\hline
		\lstinline[language=SystemVerilog]|function int prev(ref index)|   & 返回关联数组当前位置的前一个元素的索引值   \\\hline
		\lstinline[language=SystemVerilog]|function int exists(ref index)| & 判断关联数组是否存在索引值为index的元素 \\\hline
	\end{tabular}%
\end{table}%

\end{frame}

\begin{frame}[t,fragile]{关联数组的遍历}

关联数组的地址不具有连续性。

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-19},consecutivenumbers=false]%,caption=关联数组的遍历\\\lstname,label=using associutive arrays]
{src/ch2/sec6/1/test.sv}

\end{frame}

\begin{frame}[t,fragile]{关联数组的索引可以是字符串}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-14},consecutivenumbers=false]%,caption=使用带字符串索引的关联数组\\\lstname,label=using associative array with string index]
{src/ch2/sec6/2/test.sv}

\begin{lstlisting}
256
0
'{"max":1024, "min":0}
0
\end{lstlisting}

\end{frame}

\section{队列} \label{Queues}

\begin{frame}[t,fragile]{队列定义时在方括号中使用符号“\$”}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-12},consecutivenumbers=false]
{src/ch2/sec7/1/test.sv}

\begin{table}[!htb]
	\centering\captionsetup{font={scriptsize}}\scriptsize %small or scriptsize
	%\caption{队列的内置方法} \label{table Queue methods}%
	\begin{tabular}{ll}
		\hline
		\rowcolor{black!10}方法                                                 & 说明                        \\\hline
		\lstinline[language=SystemVerilog]|function int size()|               & 返回队列长度                    \\\hline
		\lstinline[language=SystemVerilog]|function void insert(index, item)| & 在索引为index的位置插入item        \\\hline
		\lstinline[language=SystemVerilog]|function element_t pop_front()|    & 弹出队列的首个元素作为方法的返回值         \\\hline
		\lstinline[language=SystemVerilog]|function element_t pop_back()|     & 弹出队列的末尾元素作为方法的返回值         \\\hline
		\lstinline[language=SystemVerilog]|function void push_front(item)|    & 将item插入到队列最前面             \\\hline
		\lstinline[language=SystemVerilog]|function void push_back(item)|     & 将item插入到队列最后面             \\\hline
		\lstinline[language=SystemVerilog]|function void delete(index)|       & 删除索引为index的元素，不加参数则删除整个队列 \\\hline
	\end{tabular}%
\end{table}%

\end{frame}

\section{数组和队列的块选} \label{Array and queue Slice part select}

\begin{frame}[t,fragile]{数组和队列的块选}

	\begin{enumerate}
		\item 非索引块选：即\texttt{[msb\_expr:lsb\_expr]}，对于数组来说，\texttt{msb\_expr}和\texttt{lsb\_expr}必须是常量整数表达式，队列则没有这个限制。
	\end{enumerate}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-21},consecutivenumbers=false]
%,caption=数组和队列的块操作\\\lstname,label=array slice operations]
{src/ch2/sec8/1/test.sv}

\end{frame}

\begin{frame}[t,fragile]{队列的内置方法}

\begin{figure}[!htb]
	\centering
	\includegraphics[scale=0.8]{queue_op.pdf}
	%\caption{队列的常用操作方法} \label{fig queue operations}
\end{figure}

\end{frame}


\begin{frame}[t,fragile]{队列方法的使用}

队列方法一次只能添加或删除一个队列元素

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-22},consecutivenumbers=false]
{src/ch2/sec7/2/test.sv}

\end{frame}

\begin{frame}[t,fragile]{使用拼接运算符操作队列}

注意“\$”在方括号中的左边或右边分别代表队列的索引下限和上限，

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-22},consecutivenumbers=false]
{src/ch2/sec7/3/test.sv}

\end{frame}

\section{数组的内置方法} \label{Array Methods}

\subsection{数组缩减方法} \label{Array Reduction Methods}

\begin{frame}[t,fragile]{数组缩减方法（reduction method）}

\begin{enumerate}
	\item 数组缩减方法（reduction method）：对非压缩整数数组的全部或部分元素进行迭代计算而得到一个数值结果。
	\item 数组缩减方法与with语句结合使用。with语句先根据表达式计算出结果序列，然后数组缩减方法对结果序列进行处理。
\end{enumerate}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-13},consecutivenumbers=false]%,caption=数组的缩减操作\\\lstname,label=using array reduction methods]
{src/ch2/sec8/1/test.sv}

\begin{lstlisting}
10 2 14 24 0
\end{lstlisting}

\end{frame}

\begin{frame}[t,fragile]{从数组或队列中随机选取元素}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-16},consecutivenumbers=false]%,caption=从关联数组中随机选取一个元素\\\lstname,label=picking a random element from an array]
{src/ch2/sec9/2/test.sv}

\begin{lstlisting}
The 3'th element a[1000]=6
\end{lstlisting}

\end{frame}

\subsection{数组定位方法} \label{Array Locator Methods}

\begin{frame}[t,fragile]{数组定位方法（locator method）返回一个队列}

数组定位方法（locator method）的返回结果一定是队列类型。

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-19},consecutivenumbers=false]
{src/ch2/sec9/3/test.sv}

\end{frame}

\begin{frame}[t,fragile]{数组定位方法（locator method）}

数组定位方法可以与with语句配合使用，返回一个满足with语句条件的元素队列或索引队列。

\begin{table}[!htb]
	\centering\captionsetup{font={footnotesize}}\footnotesize %small or scriptsize
	%\caption{常用的数组定位方法} \label{some array locator methods}%
	\begin{tabular}{ll}
		\hline
		\rowcolor{black!10}方法名                                 & 说明                \\\hline
		\lstinline[language=SystemVerilog]|find()|             & 返回满足表达式的全部元素      \\\hline
		\lstinline[language=SystemVerilog]|find_index()|       & 返回满足表达式的全部元素的索引   \\\hline
		\lstinline[language=SystemVerilog]|find_first()|       & 返回满足表达式的第一个元素     \\\hline
		\lstinline[language=SystemVerilog]|find_first_index()| & 返回满足表达式的第一个元素的索引  \\\hline
		\lstinline[language=SystemVerilog]|find_last()|        & 返回满足表达式的最后一个元素    \\\hline
		\lstinline[language=SystemVerilog]|find_last_index()|  & 返回满足表达式的最后一个元素的索引 \\\hline
	\end{tabular}%
\end{table}%

\end{frame}

\begin{frame}[t,fragile]{数组定位方法（locator method）}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-20},consecutivenumbers=false]%,caption=数组定位方法的使用\\\lstname,label=Array locator methods: find]
{src/ch2/sec9/4/test.sv}

\end{frame}

\subsection{数组排序方法} \label{Array Sorting and Ordering}

\begin{frame}[t,fragile]{数组的排序方法（ordering method）}

排序方法直接对数组本身操作，它们会改变数组的内容。

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-16},consecutivenumbers=false]%,caption=数组排序方法的使用\\\lstname,label=sorting an array]
{src/ch2/sec9/5/test.sv}

reverse和shuffle方法不能和with语句配合使用，它们的作用范围是整个数组。

\end{frame}

\begin{frame}[t,fragile]{数组的排序方法（ordering method）}

使用子域对一个结构类型数组排序。定长数组、动态数组和队列支持排序方法，关联数组不支持排序方法。

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-13},consecutivenumbers=false]%,caption=对结构类型数组排序\\\lstname,label=sorting an array of structures]
{src/ch2/sec9/6/test.sv}

\begin{lstlisting}
color='{'{r:'h1, g:'h4, b:'h7}, '{r:'h1, g:'h5, b:'h9}, '{r:'h2, g:'h5, b:'h8}}
color='{'{r:'h1, g:'h4, b:'h7}, '{r:'h2, g:'h5, b:'h8}, '{r:'h1, g:'h5, b:'h9}}
\end{lstlisting}

\end{frame}

\section{自定义数据类型} \label{Creating New Types with typedef}

\begin{frame}[t,fragile]{typedef}

本书约定除了uint，其他自定义类型都带后缀“\_t”。

\begin{lstlisting}[language=SystemVerilog,numbers=left,consecutivenumbers=false]
typedef bit [31:0] uint; // typedef int unsigned uint;
uint a;
\end{lstlisting}

使用关键字typedef自定义数组类型时需要把数组索引放在新类型名后面。

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-11},consecutivenumbers=false]
{src/ch2/sec10/1/test.sv}

\end{frame}

\section{结构和联合} \label{Creating User-Defined Structures}

\subsection{结构} \label{Structures}

\begin{frame}[t,fragile]{结构（structure）}

结构（structure）是一种将多个变量组织到一起的复杂数据类型，结构可以使用关键字struct定义。

\begin{lstlisting}[language=SystemVerilog,numbers=left,consecutivenumbers=false]
struct {
	bit [7:0] r;
	bit [7:0] g;
	bit [7:0] b;
} pixel;
\end{lstlisting}

\begin{figure}[!htb]
	\centering\captionsetup{font={footnotesize}}\footnotesize %small or scriptsize
	\scalebox{1.0}{
		\begin{tikzpicture}
			\tikzstyle{every node}=[font=\normalsize]
			% \draw[step=1,color=gray] (0,0) grid (28,6);
			\foreach \y in {0,0.7,1.4}
				{
					\node[draw,rectangle,minimum height=0.7cm,minimum width=8.0cm] at (4,\y+0.35) {高24位未使用};
				}
			%\foreach \x/\xtext in {8/7,8.7/6,9.4/5,10.1/4,10.8/3,11.5/2,12.2/1,12.9/0}
			\node[draw,fill={black!10},rectangle,minimum height=0.7cm,minimum width=2cm] at (9,0.35) {b};
			\node[draw,fill={black!10},rectangle,minimum height=0.7cm,minimum width=2cm] at (9,1.05) {g};
			\node[draw,fill={black!10},rectangle,minimum height=0.7cm,minimum width=2cm] at (9,1.75) {r};
		\end{tikzpicture}
	}
	%\caption{非压缩结构的存储方式} \label{Unpacked struct storage}
\end{figure}

\end{frame}

\begin{frame}[t,fragile]{}

使用typedef创建一个自定义结构类型，这样可以方便的使用自定义结构类型创建结构变量。

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-13},consecutivenumbers=false]
{src/ch2/sec11/1/test.sv}

\begin{lstlisting}
pixel='{r:'h1, g:'h2, b:'h3}
packed_pixel='{r:'h1, g:'h2, b:'h3}
\end{lstlisting}

\begin{figure}[!htb]
	\centering\captionsetup{font={footnotesize}}\footnotesize %small or scriptsize
	\scalebox{0.8}{
		\begin{tikzpicture}
			\tikzstyle{every node}=[font=\normalsize]
			% \draw[step=1,color=gray] (0,0) grid (28,6);
			\node[draw,rectangle,minimum height=0.7cm,minimum width=2.5cm] at (1.25,0.35) {未使用};
			\foreach \x/\xtext in {2.5/r,5/g,7.5/b}
				{ \node[draw,fill={black!10},rectangle,minimum height=0.7cm,minimum width=2.5cm] at (\x+1.25,0.35) {\xtext}; }
			\node at (-1.5,0.35) {packed\_pixel\_s};
		\end{tikzpicture}
	}
	%\caption{压缩结构的存储方式} \label{Packed struct storage}
\end{figure}

\end{frame}

\subsection{联合} \label{Making a Union of Several Types}

\begin{frame}[t,fragile]{}

联合（union）是一种特殊的数据类型，一个联合中可以包含多种不同数据类型的成员，所有成员共享同一个存储空间，占据存储空间最大的成员决定了联合占据存储空间的大小。访问不同的成员等同于使用不同的数据类型格式访问同一块存储空间。

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-11},consecutivenumbers=false]%,caption=使用typedef创建自定义联合类型\\\lstname,label=Using typedef to create a union]
{src/ch2/sec11/2/test.sv}

\begin{lstlisting}
uni.bu=255, uni.bs=-1
\end{lstlisting}

\end{frame}

\section{枚举} \label{Enumerated Types}

\subsection{定义枚举类型} \label{Defining Enumerated Types}

\begin{frame}[t,fragile]{定义枚举类型}

枚举（enumeration）是一些符号常量的集合，每个符号和一个整数常量值绑定。编译器对枚举的认知就是符号常量所绑定的那个常量值。枚举变量只能在由枚举名构成的数值范围内取值。

\begin{lstlisting}[language=SystemVerilog,numbers=left,consecutivenumbers=false]%,caption=使用enum定义枚举变量,label=A simple enumerated type]
enum {INIT, DECODE, IDLE} pstate, nstate;
enum bit [1:0] {OKAY, ERROR, RETRY, SPLIT} hresp;
\end{lstlisting}

枚举变量表示当前枚举名的取值，使用name方法获取枚举变量对应的枚举名。

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-15},consecutivenumbers=false]
{src/ch2/sec12/1/test.sv}

\end{frame}

\subsection{枚举的方法} \label{Routines for Enumerated Types}

\begin{frame}[t,fragile]{枚举的方法}

枚举变量默认按int类型存储，它的默认值是0。所以在定义枚举类型时一定要加入与0绑定的枚举名。

\begin{lstlisting}[language=SystemVerilog,numbers=left,consecutivenumbers=false]
typedef enum {IDLE, INIT = 2, DECODE} state_e;
\end{lstlisting}

在枚举名列表的开始（或结尾）位置调用prev（或next）方法，它们会以循环的方式返回结尾（或开始）位置的枚举名。

\begin{table}[!htb]
	\centering\captionsetup{font={footnotesize}}\footnotesize %small or scriptsize
	%\caption{遍历枚举名的方法} \label{enum methods}%
	\begin{tabular}{ll}
		\hline
		\rowcolor{black!10}方法                                                      & 说明            \\\hline
		\lstinline[language=SystemVerilog]|function enum first()|                  & 返回第一个枚举名      \\\hline
		\lstinline[language=SystemVerilog]|function enum last()|                   & 返回最后一个枚举名     \\\hline
		\lstinline[language=SystemVerilog]|function enum next(int unsigned N = 1)| & 返回当前位置后第N个枚举名 \\\hline
		\lstinline[language=SystemVerilog]|function enum prev(int unsigned N = 1)| & 返回当前位置前第N个枚举名 \\\hline
		\lstinline[language=SystemVerilog]|function int num()|                     & 返回队列的长度       \\\hline
		\lstinline[language=SystemVerilog]|function string name()|                 & 以字符串的形式返回枚举名  \\\hline
	\end{tabular}%
\end{table}%

\end{frame}

\begin{frame}[t,fragile]{遍历枚举名}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-14},consecutivenumbers=false]%,caption=遍历所有枚举名\\\lstname,label=stepping through all enumerated members]
{src/ch2/sec12/2/test.sv}

\begin{lstlisting}
State IDLE = 0
State INIT = 1
State DECODE = 2
\end{lstlisting}

\end{frame}

\subsection{枚举变量和类型转换} \label{Converting to and from Enumerated Types}

\begin{frame}[t,fragile]{枚举变量和类型转换}

函数\$cast尝试将int变量s赋值给枚举变量state。如果赋值成功\$cast返回1，如果变量s的数值越界则不进行赋值并返回0。

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-17},consecutivenumbers=false]
{src/ch2/sec12/3/test.sv}

\begin{lstlisting}
State DECODE = 2
State  = 3
\end{lstlisting}

\end{frame}

\section{流操作符} \label{Streaming Operators}

\begin{frame}[t,fragile]{流操作符}

流操作符可以将表达式、结构或数组等源数据打包成一个比特流。

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-21},consecutivenumbers=false]
{src/ch2/sec13/1/test.sv}

\end{frame}

\begin{frame}[t,fragile]{}

定长数组、动态数组和队列都支持流操作符，流操作符可以轻松实现不规则位宽数据流间的转换。

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={6-14},consecutivenumbers=false]%,caption=使用流操作符进行队列间的转换\\\lstname,label=converting between queues with streaming operator]
{src/ch2/sec13/2/test.sv}

\begin{lstlisting}
000000000100000000100000000011
00000000010000000010000000001100
'{'h0, 'h40, 'h20, 'hc}
\end{lstlisting}

数组间使用流操作符的常见错误是索引不匹配。数组的缩写定义[high]等同于[0:high]，而很多数组会使用[high:0]的形式定义，两者使用流操作符赋值时会造成元素倒序。同样，如果使用流操作符将bit [7:0] src [255:0]的非压缩数组赋值给bit [7:0] [255:0] dst的压缩数组，则数值的顺序会被打乱，正确的压缩字节数组定义形式应该是bit[255:0] [7:0] dst。

\end{frame}

\begin{frame}[t,fragile]{}

流操作符也可用来将结构压缩或者解压缩到字节数组中。

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-18},consecutivenumbers=false]%,caption=使用流操作符在结构和数组间进行转换\\\lstname,label=converting between structure and array with streaming operators]
{src/ch2/sec13/3/test.sv}

\begin{lstlisting}
b='{'h12, 'h34, 'h56, 'h78, 'h9a}
st='{a:305419896, b:154}
\end{lstlisting}

\end{frame}

\section{包} \label{Packages}

\begin{frame}[t,fragile]{包}

\begin{enumerate}
	\item `include语句导入的头文件的内容在设计中都是可见的。
	\item 使用import语句和域操作符“::”导入包（package）的部分或全部内容，局部可见。
\end{enumerate}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={4-12},consecutivenumbers=false]
{src/ch2/sec14/1/test.sv}

\end{frame}

\begin{frame}[t,fragile]{}

\lstinputlisting[language=SystemVerilog,numbers=left,linerange={14-25},consecutivenumbers=false]
{src/ch2/sec14/1/test.sv}

\begin{lstlisting}
message in test, message in pkg_2d
\end{lstlisting}

在包中，只有其内部定义的内容和从其他包中导入的符号可见。不能通过层次化引用包外的信号、例程或者模块。可以认为包是完全独立的，可以在任何所需位置插入包，包没有外部关联。

\end{frame}

\end{document}
